package com.liyunc.demo.bundle.security.config;

import com.liyunc.demo.bundle.security.filter.BaseAuthFilter;
import com.liyunc.demo.bundle.security.filter.BaseAuthProvider;
import com.liyunc.demo.bundle.security.filter.JwtAuthFilter;
import com.liyunc.demo.bundle.security.filter.JwtAuthProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AnonymousAuthenticationProvider;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

/**
 * @author liyuncong
 * @version 1.0
 * @file SecurityConfig, java
 * @brief SecurityConfig
 * @details SecurityConfig
 * @date 2022-02-21
 *
 * Edit History
 * ----------------------------------------------------------------------------
 * DATE                     NAME               DESCRIPTION
 * 2022-03-26               liyuncong        Created
 */
@Configuration
@EnableWebSecurity
@EnableWebMvc
@RequiredArgsConstructor
@Slf4j
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private BaseAuthFilter baseAuthFilter;
    @Autowired
    private BaseAuthProvider baseAuthProvider;

    @Autowired
    private JwtAuthFilter jwtAuthFilter;
    @Autowired
    private JwtAuthProvider jwtAuthProvider;

    @Autowired
    private AnonymousAuthenticationFilter anonymousAuthenticationFilter;
    @Autowired
    private AnonymousAuthenticationProvider anonymousAuthenticationProvider;


    /**
     * 登录配置.
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        HttpSecurity httpSecurity = http
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
            .addFilterBefore(baseAuthFilter, JwtAuthFilter.class)
            .addFilterBefore(anonymousAuthenticationFilter, AnonymousAuthenticationFilter.class);
        AuthorizeHttpRequestsConfigurer<HttpSecurity>
            .AuthorizationManagerRequestMatcherRegistry result =
            httpSecurity.authorizeHttpRequests();
        result
            .antMatchers("/api/v1/token", "/api/v1/token/logout","/api/v1/people")
            .permitAll()
            .antMatchers("/api/v1/**")
            .authenticated()
            .and()
            .csrf()
            .disable()
            .sessionManagement(
                (session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .exceptionHandling()
            .authenticationEntryPoint(
                new LoginUrlAuthenticationEntryPoint("/api/v1/token"));
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .authenticationProvider(baseAuthProvider)
            .authenticationProvider(jwtAuthProvider)
            .authenticationProvider(anonymousAuthenticationProvider);
    }

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

}